package com.tmc.service.intair;

import java.util.AbstractMap;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.CompletionService;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.tmc.bean.common.CommonResult;
import com.tmc.bean.common.ContextInfo;
import com.tmc.bean.common.Pagination;
import com.tmc.constant.NoticeConstant;
import com.tmc.constant.TaskConstant;
import com.tmc.constant.NoticeConstant.NoticeStatus;
import com.tmc.constant.TaskConstant.TaskStatus;
import com.tmc.dao.impl.intair.IntairChaseCabinDaoImpl;
import com.tmc.entity.common.EthNotice;
import com.tmc.entity.intair.IntairChaseCabin;
import com.tmc.entity.intair.IntairFlight;
import com.tmc.entity.intair.IntairOrder;
import com.tmc.entity.intair.IntairPassenger;
import com.tmc.entity.intair.IntairSegment;
import com.tmc.service.common.NoticeServiceImpl;
import com.tmc.util.DateUtil;
import com.tmc.util.ObjectUtil;
import com.tmc.vendor.asms.bean.FlightBean;
import com.tmc.vendor.asms.bean.SegmentBean;
import com.tmc.vendor.asms.util.Asms10000Util;

@Service
@Transactional
public class IntairChaseCabinProcessServiceImpl {

	private Log logger = LogFactory.getLog(this.getClass());

	@Autowired
	private IntairChaseCabinDaoImpl dao;

	@Autowired
	private NoticeServiceImpl noticeService;

	public List<IntairChaseCabin> findTasks() {
		return dao.findWait(null, 5);
	}

	// 处理单个pnr
	public void process(IntairChaseCabin task) {
		System.out.println("处理" + task.getPnr());
		// 过期失效
		if (isDead(task)) {
			return;
		}
		task.setRunCount(task.getRunCount() + 1);
		try {
			CommonResult qtb = Asms10000Util.getLowerCabin(task);
			if (!qtb.isSuccess()) {
				ObjectUtil.updateBaseInfo(task, ContextInfo.getTimerContextInfo());
				dao.update(task);
				return;
			}
			task.setNewPnr((String) qtb.getObj());
			task.setStatus(TaskStatus.SUCCESS.getStatus());
			ObjectUtil.updateBaseInfo(task, ContextInfo.getTimerContextInfo());
			dao.update(task);
			// 发送短信
			this.saveNotice(task);
		} catch (Exception e) {
			logger.error("执行任务出错！", e);
			task.setStatus(TaskStatus.FAIL.getStatus());
			ObjectUtil.updateBaseInfo(task, ContextInfo.getTimerContextInfo());
			dao.update(task);
		}
		/*
		 * final String[] segments = task.getRouting().split("/"); final
		 * String[] airlines = task.getAirlines() .split("/"); final String[]
		 * dates = task.getDepartDates().split("/"); final String[] cabins =
		 * task.getCabins().split("/"); final String[] flightNos =
		 * task.getFlightNos().split("/"); ExecutorService threadPool =
		 * Executors.newFixedThreadPool(segments.length);
		 * CompletionService<Entry<Integer, CabinBean>> completion = new
		 * ExecutorCompletionService<Entry<Integer, CabinBean>>( threadPool);
		 * for (int i = 0; i < segments.length; i++) { final int index = i;
		 * completion.submit(new Callable<Entry<Integer, CabinBean>>() {
		 * 
		 * @Override public Entry<Integer, CabinBean> call() { try {
		 * List<FlightBean> flights =
		 * AsmsUtil.getAVH(segments[index].split("-")[0],
		 * segments[index].split("-")[1], airlines[index],
		 * dates[index].split(" ")[0], dates[index].split(" ")[1]); FlightBean
		 * flight = getTheFlight(flights, flightNos[index]); return
		 * getCompileReuslt(index, null, cabins[index]); } catch (Exception e) {
		 * logger.error("定时器avh出错！", e); return null; } } }); } Map<Integer,
		 * CabinBean> map = this.getThreadPoolResult(completion,
		 * segments.length); boolean isSucess = false; StringBuilder sb = new
		 * StringBuilder("pnr:" + task.getPnr() + ","); for (Integer index :
		 * map.keySet()) { CabinBean bean = map.get(index); if (bean.isLower())
		 * { isSucess = true; logger.error(task.getPnr() + "航段" +
		 * segments[index] + "，" + cabins[index] + "舱，存在更低舱位" + bean.getCabin()
		 * + "舱。"); sb.append("航段" + segments[index] + "，" + cabins[index] +
		 * "舱，存在更低舱位" + bean.getCabin() + "舱。"); } } // if (isSucess) {
		 * task.setStatus(TaskStatus.SUCCESS.getStatus());
		 * ObjectUtil.updateBaseInfo(task, ContextInfo.getTimerContextInfo());
		 * dao.update(task); // 发送短信 AsmsUtil.sendSms(task.getNoticePhone(),
		 * sb.toString()); }
		 */
	}

	private void saveNotice(IntairChaseCabin task) throws Exception {
		String content = "【降舱】您的编码" + task.getPnr() + "已抓取到更低舱位，新的编码为:" + task.getNewPnr() + "，请及时处理！";
		if (ObjectUtil.noText(task.getNewPnr())){
			content = "【降舱】您的编码" + task.getPnr() + "已查询到更低舱位，舱位充足，请及时处理！";
		}
		// 发送短信
		EthNotice notice = new EthNotice();
		notice.setSendTarget(task.getNoticePhone());
		notice.setToSendTime(DateUtil.toLongDate(new Date()));
		notice.setNoticeType(NoticeConstant.NOTICE_TYPE_SMS);
		notice.setContent(content);
		notice.setStatus(NoticeStatus.WAITING.getStatus());
		noticeService.save(null, notice);
	}

	private boolean isDead(IntairChaseCabin task) {
		Long deadline = task.getDeadline();
		Long current = DateUtil.toLongDate(new Date());
		if (deadline <= current) {
			task.setStatus(TaskStatus.DEAD.getStatus());
			ObjectUtil.updateBaseInfo(task, ContextInfo.getTimerContextInfo());
			dao.update(task);
		}
		return false;
	}

	@SuppressWarnings("unused")
	private Map<Integer, CabinBean> getThreadPoolResult(CompletionService<Entry<Integer, CabinBean>> completion,
			int size) throws Exception {
		Map<Integer, CabinBean> map = new HashMap<Integer, CabinBean>();
		for (int i = 0; i < size; i++) {
			Entry<Integer, CabinBean> entry = completion.take().get();
			map.put(entry.getKey(), entry.getValue());
		}
		return map;
	}

	protected Entry<Integer, CabinBean> getCompileReuslt(int index, SegmentBean segment, String dbCabin) {
		LinkedHashMap<String, Integer> cabinMap = segment.getCabinMap();
		String lowestCabin = dbCabin;
		Integer lowestCabinNum = 0;
		boolean isLower = false;
		for (String cabin : cabinMap.keySet()) {
			Integer num = cabinMap.get(cabin);
			if (num > 0) {
				lowestCabin = cabin;
				lowestCabinNum = num;
			}
			if (cabin.equals(dbCabin)) {
				isLower = true;
			}
		}
		CabinBean bean = new CabinBean(isLower, lowestCabin, lowestCabinNum);
		return new AbstractMap.SimpleEntry<Integer, CabinBean>(index, bean);
	}

	protected FlightBean getTheFlight(List<FlightBean> flights, String flightNo) {
		for (FlightBean flight : flights) {
			SegmentBean segment = flight.getSegments().get(0);
			if (segment.getFlightNo().equals(flightNo)) {
				return null;
			}
		}
		return null;
	}

	public Pagination<IntairChaseCabin> findByCon(ContextInfo context, IntairChaseCabin cond, Integer pageIndex,
			Integer pageSize) {
		Pagination<IntairChaseCabin> result = dao.findByCon(context, cond, pageIndex, pageSize);
		this.setExtInfo(result);
		return result;
	}
	
	public Pagination<IntairChaseCabin> findCurrentByCon(ContextInfo context, IntairChaseCabin cond, Integer pageIndex,
			Integer pageSize) {
		Pagination<IntairChaseCabin> result = dao.findCurrent(context, cond, pageIndex, pageSize);
		this.setExtInfo(result);
		return result;
	}
	
	public Pagination<IntairChaseCabin> findHistoryByCon(ContextInfo context, IntairChaseCabin cond, Integer pageIndex,
			Integer pageSize) {
		Pagination<IntairChaseCabin> result = dao.findHistory(context, cond, pageIndex, pageSize);
		this.setExtInfo(result);
		return result;
	}

	private void setExtInfo(Pagination<IntairChaseCabin> result) {
		if (result == null || result.getItems() == null || result.getItems().isEmpty()) {
			return;
		}
		for (IntairChaseCabin task : result.getItems()) {
			task.setStatusName(TaskConstant.getTaskStatusName(task.getStatus()));
		}
	}

	public CommonResult save(ContextInfo context, IntairChaseCabin cond) {
		CommonResult check = this.check(context, cond);
		if (!check.isSuccess()) {
			return check;
		}
		try {
			IntairOrder order = Asms10000Util.getQTE(cond.getPnr());
			cond = this.buildChaseCabin(context, order, cond, order.getTotalAmount());
			cond.setStatus(TaskStatus.WAITING.getStatus());
			cond.setRunCount(0L);
			cond.setDeadline(DateUtil.toLongDate(DateUtil.addDate(new Date(), 1)));
			if (ObjectUtil.noText(cond.getNoticePhone())) {
				cond.setNoticePhone("13066832530");
			}
			ObjectUtil.setBaseInfo(cond, context);
			dao.insert(cond);
			//
			// orderService.save(context, order);
		} catch (Exception e) {
			logger.error("保存追位出错！", e);
			return CommonResult.makeFail("保存追位出错！" + e.getMessage());
		}
		return CommonResult.makeSuccess();
	}

	private CommonResult check(ContextInfo context, IntairChaseCabin cond) {
		if (ObjectUtil.noText(cond.getPnr())) {
			return CommonResult.makeFail("pnr不能为空！");
		}
		List<IntairChaseCabin> list = dao.findByPNR(context, cond.getPnr());
		if (list != null && !list.isEmpty()) {
			return CommonResult.makeFail("已存在相同PNR的降舱任务!");
		}
		return CommonResult.makeSuccess();
	}

	private IntairChaseCabin buildChaseCabin(ContextInfo context, IntairOrder order, IntairChaseCabin cond,
			Double totalPrice) {
		List<IntairFlight> flights = order.getFlights();
		List<IntairPassenger> passengers = order.getPassengers();
		StringBuilder routing = new StringBuilder();
		StringBuilder cabins = new StringBuilder();
		StringBuilder airlines = new StringBuilder();
		StringBuilder pass = new StringBuilder();
		StringBuilder dates = new StringBuilder();
		StringBuilder flightNos = new StringBuilder();
		for (IntairFlight flight : flights) {
			for (IntairSegment segment : flight.getSegments()) {
				routing.append(segment.getDeparture()).append("-").append(segment.getArrival()).append("/");
				cabins.append(segment.getBookingCode()).append("/");
				airlines.append(segment.getAirline()).append("/");
				dates.append(segment.getDepartureDate()).append(" ").append(segment.getDepartureTime()).append("/");
				flightNos.append(segment.getFlightNo()).append("/");
			}
			routing = routing.deleteCharAt(routing.length() - 1);
			routing.append("@");
		}
		for (IntairPassenger passenger : passengers) {
			pass.append(passenger.getPassengerNameEn()).append(",");
		}
		cond.setRouting(routing.substring(0, routing.length() - 1));
		cond.setDepartDates(dates.substring(0, dates.length() - 1));
		cond.setCabins(cabins.substring(0, cabins.length() - 1));
		cond.setAirlines(airlines.substring(0, airlines.length() - 1).split("/")[0]);
		cond.setPassengers(pass.substring(0, pass.length() - 1));
		cond.setFlightNos(flightNos.substring(0, flightNos.length() - 1));
		cond.setTotalPrice(totalPrice);
		return cond;
	}

	public IntairChaseCabin getById(ContextInfo contextInfo, Long chaseCabinId) {
		return dao.getById(chaseCabinId);
	}

	public CommonResult delete(ContextInfo context, Long chaseCabinId) {
		if (chaseCabinId == null) {
			return CommonResult.makeFail("请选择至少一条数据！");
		}
		IntairChaseCabin bean = this.getById(context, chaseCabinId);
		if (bean == null) {
			return CommonResult.makeFail("数据不存在！");
		}
		bean.setEnabledFlag("N");
		ObjectUtil.updateBaseInfo(bean, context);
		dao.update(bean);
		return CommonResult.makeSuccess();
	}

	public CommonResult deletes(ContextInfo contextInfo, String chaseCabinIds) {
		if (ObjectUtil.noText(chaseCabinIds)) {
			return CommonResult.makeFail("请选择至少一条数据！");
		}
		for (String str : chaseCabinIds.split(",")) {
			Long id = Long.valueOf(str);
			dao.delete(id);
		}
		return CommonResult.makeSuccess();
	}

	public CommonResult changeStatus(ContextInfo context, Long chaseCabinId, String status) {
		if (chaseCabinId == null) {
			return CommonResult.makeFail("请选择至少一条数据！");
		}
		IntairChaseCabin dbObj = dao.getById(chaseCabinId);
		if (dbObj == null) {
			return CommonResult.makeFail("不存在ID为" + chaseCabinId + "的任务数据！");
		}
		dbObj.setStatus(status);
		ObjectUtil.updateBaseInfo(dbObj, context);
		dao.update(dbObj);
		return CommonResult.makeSuccess();
	}

	public CommonResult changeStatus(ContextInfo context, String chaseCabinIds, String status) {
		if (ObjectUtil.noText(chaseCabinIds)) {
			return CommonResult.makeFail("请选择至少一条数据！");
		}
		for (String str : chaseCabinIds.split(",")) {
			Long id = Long.valueOf(str);
			changeStatus(context, id, status);
		}
		return CommonResult.makeSuccess();
	}

	public class CabinBean {

		private boolean isLower;
		private String cabin;
		private Integer num;

		public CabinBean(boolean isLower, String cabin, Integer num) {
			this.isLower = isLower;
			this.cabin = cabin;
			this.num = num;
		}

		public String getCabin() {
			return cabin;
		}

		public void setCabin(String cabin) {
			this.cabin = cabin;
		}

		public Integer getNum() {
			return num;
		}

		public void setNum(Integer num) {
			this.num = num;
		}

		public boolean isLower() {
			return isLower;
		}

		public void setLower(boolean isLower) {
			this.isLower = isLower;
		}
	}

}
